{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mapping using ploty\n",
    "- example codes on the [Plotly Pandas website](https://plot.ly/pandas/#maps)\n",
    "- offline mode to avoid \"Aw, snap!\" error messages.\n",
    "- survey three major categories of maps:\n",
    " - [Scatter plots](https://plot.ly/pandas/scatter-plots-on-maps/)\n",
    " - [Choropleth maps](https://plot.ly/pandas/choropleth-maps/) \n",
    " - [Bubble maps](https://plot.ly/pandas/bubble-maps/)\n",
    " - c.f. mapping in Tableau\n",
    "  - [Chinese](https://onlinehelp.tableau.com/current/pro/desktop/zh-cn/help.html#maps_build.html)\n",
    "  - [English](https://onlinehelp.tableau.com/current/pro/desktop/en-us/help.html#maps_build.html)\n",
    "- other maps\n",
    " - [Lines on maps](https://plot.ly/pandas/lines-on-maps/)\n",
    "- good example to tell a story using maps\n",
    " - [New Walmart Stores per year 1962-2006](https://plot.ly/pandas/map-subplots-and-small-multiples/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## notes to make it work\n",
    "- install necessary packages plotly\n",
    "- codes need to be fixed to go \"offline\"\n",
    " - import plotly.offline as py  # import plotly.plotly as py\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Scatter plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "codes here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Choropleth maps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "codes here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Bubble maps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Learn about API authentication here: https://plot.ly/pandas/getting-started\n",
    "# Find your api_key here: https://plot.ly/settings/ap\n",
    "\n",
    "import plotly.offline as py  # import plotly.plotly as py\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2014_us_cities.csv')\n",
    "df.head()\n",
    "\n",
    "df['text'] = df['name'] + '<br>Population ' + (df['pop']/1e6).astype(str)+' million'\n",
    "limits = [(0,2),(3,10),(11,20),(21,50),(50,3000)]\n",
    "colors = [\"rgb(0,116,217)\",\"rgb(255,65,54)\",\"rgb(133,20,75)\",\"rgb(255,133,27)\",\"rgb(255,220,0)\"]\n",
    "cities = []\n",
    "scale = 50000\n",
    "\n",
    "for i in range(len(limits)):\n",
    "    lim = limits[i]\n",
    "    df_sub = df[lim[0]:lim[1]]\n",
    "    city = dict(\n",
    "        type = 'scattergeo',\n",
    "        locationmode = 'USA-states',\n",
    "        lon = df_sub['lon'],\n",
    "        lat = df_sub['lat'],\n",
    "        text = df_sub['text'],\n",
    "        sizemode = 'diameter',\n",
    "        marker = dict( \n",
    "            size = df_sub['pop']/scale, \n",
    "            color = colors[i],\n",
    "            line = dict(width = 2,color = 'black')\n",
    "        ),\n",
    "        name = '{0} - {1}'.format(lim[0],lim[1]) )\n",
    "    cities.append(city)\n",
    "\n",
    "layout = dict(\n",
    "        title = '2014 US city populations<br>(Click legend to toggle traces)',\n",
    "        showlegend = True,\n",
    "        geo = dict(\n",
    "            scope='usa',\n",
    "            projection=dict( type='albers usa' ),\n",
    "            showland = True,\n",
    "            landcolor = 'rgb(217, 217, 217)',       \n",
    "            subunitwidth=1,\n",
    "            countrywidth=1,\n",
    "            subunitcolor=\"rgb(255, 255, 255)\",\n",
    "            countrycolor=\"rgb(255, 255, 255)\"           \n",
    "        ),  \n",
    "    )\n",
    "    \n",
    "fig = dict( data=cities, layout=layout )\n",
    "#url = py.plot( fig, validate=False, filename='d3-bubble-map-populations' )\n",
    "url = py.plot( fig, validate=False, filename='d3-bubble-map-populations.html' )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Lines on maps"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "codes here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### New Walmart Stores per year 1962-2006"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\ProgramData\\Anaconda3\\lib\\site-packages\\plotly\\offline\\offline.py:459: UserWarning:\n",
      "\n",
      "Your filename `US Walmart growth.htm` didn't end with .html. Adding .html to the end of your file.\n",
      "\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "Object of type 'range' is not JSON serializable",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-18-f0c9f971fde3>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m    119\u001b[0m \u001b[0mfig\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m{\u001b[0m \u001b[1;34m'data'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mdata\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'layout'\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mlayout\u001b[0m \u001b[1;33m}\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    120\u001b[0m \u001b[1;31m#py.iplot( fig, filename='US Walmart growth', height=900, width=1000 )\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 121\u001b[1;33m \u001b[0murl\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpy\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[1;33m(\u001b[0m \u001b[0mfig\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalidate\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mFalse\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m'US Walmart growth.htm'\u001b[0m \u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\plotly\\offline\\offline.py\u001b[0m in \u001b[0;36mplot\u001b[1;34m(figure_or_data, show_link, link_text, validate, output_type, include_plotlyjs, filename, auto_open, image, image_filename, image_width, image_height, config)\u001b[0m\n\u001b[0;32m    467\u001b[0m     plot_html, plotdivid, width, height = _plot_html(\n\u001b[0;32m    468\u001b[0m         \u001b[0mfigure_or_data\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mconfig\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalidate\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 469\u001b[1;33m         '100%', '100%', global_requirejs=False)\n\u001b[0m\u001b[0;32m    470\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    471\u001b[0m     \u001b[0mresize_script\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m''\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\plotly\\offline\\offline.py\u001b[0m in \u001b[0;36m_plot_html\u001b[1;34m(figure_or_data, config, validate, default_width, default_height, global_requirejs)\u001b[0m\n\u001b[0;32m    180\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    181\u001b[0m     \u001b[0mplotdivid\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0muuid\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0muuid4\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 182\u001b[1;33m     \u001b[0mjdata\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0m_json\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfigure\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'data'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcls\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mutils\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mPlotlyJSONEncoder\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    183\u001b[0m     jlayout = _json.dumps(figure.get('layout', {}),\n\u001b[0;32m    184\u001b[0m                           cls=utils.PlotlyJSONEncoder)\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\json\\__init__.py\u001b[0m in \u001b[0;36mdumps\u001b[1;34m(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)\u001b[0m\n\u001b[0;32m    236\u001b[0m         \u001b[0mcheck_circular\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mcheck_circular\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mallow_nan\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mallow_nan\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mindent\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mindent\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    237\u001b[0m         \u001b[0mseparators\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mseparators\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdefault\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mdefault\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0msort_keys\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0msort_keys\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 238\u001b[1;33m         **kw).encode(obj)\n\u001b[0m\u001b[0;32m    239\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    240\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\plotly\\utils.py\u001b[0m in \u001b[0;36mencode\u001b[1;34m(self, o)\u001b[0m\n\u001b[0;32m    134\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    135\u001b[0m         \u001b[1;31m# this will raise errors in a normal-expected way\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 136\u001b[1;33m         \u001b[0mencoded_o\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msuper\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mPlotlyJSONEncoder\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mencode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mo\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    137\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    138\u001b[0m         \u001b[1;31m# now:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\json\\encoder.py\u001b[0m in \u001b[0;36mencode\u001b[1;34m(self, o)\u001b[0m\n\u001b[0;32m    197\u001b[0m         \u001b[1;31m# exceptions aren't as detailed.  The list call should be roughly\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    198\u001b[0m         \u001b[1;31m# equivalent to the PySequence_Fast that ''.join() would do.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 199\u001b[1;33m         \u001b[0mchunks\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0miterencode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mo\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0m_one_shot\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;32mTrue\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    200\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    201\u001b[0m             \u001b[0mchunks\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mchunks\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\json\\encoder.py\u001b[0m in \u001b[0;36miterencode\u001b[1;34m(self, o, _one_shot)\u001b[0m\n\u001b[0;32m    255\u001b[0m                 \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mkey_separator\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitem_separator\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msort_keys\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    256\u001b[0m                 self.skipkeys, _one_shot)\n\u001b[1;32m--> 257\u001b[1;33m         \u001b[1;32mreturn\u001b[0m \u001b[0m_iterencode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mo\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    258\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    259\u001b[0m def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\site-packages\\plotly\\utils.py\u001b[0m in \u001b[0;36mdefault\u001b[1;34m(self, obj)\u001b[0m\n\u001b[0;32m    202\u001b[0m             \u001b[1;32mexcept\u001b[0m \u001b[0mNotEncodable\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    203\u001b[0m                 \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 204\u001b[1;33m         \u001b[1;32mreturn\u001b[0m \u001b[0m_json\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mJSONEncoder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdefault\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    205\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    206\u001b[0m     \u001b[1;33m@\u001b[0m\u001b[0mstaticmethod\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mC:\\ProgramData\\Anaconda3\\lib\\json\\encoder.py\u001b[0m in \u001b[0;36mdefault\u001b[1;34m(self, o)\u001b[0m\n\u001b[0;32m    178\u001b[0m         \"\"\"\n\u001b[0;32m    179\u001b[0m         raise TypeError(\"Object of type '%s' is not JSON serializable\" %\n\u001b[1;32m--> 180\u001b[1;33m                         o.__class__.__name__)\n\u001b[0m\u001b[0;32m    181\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    182\u001b[0m     \u001b[1;32mdef\u001b[0m \u001b[0mencode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mo\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mTypeError\u001b[0m: Object of type 'range' is not JSON serializable"
     ]
    }
   ],
   "source": [
    "import plotly.offline as py  # import plotly.plotly as py\n",
    "import pandas as pd\n",
    "df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/1962_2006_walmart_store_openings.csv')\n",
    "df.head()\n",
    "\n",
    "data = []\n",
    "layout = dict(\n",
    "    title = 'New Walmart Stores per year 1962-2006<br>\\\n",
    "Source: <a href=\"http://www.econ.umn.edu/~holmes/data/WalMart/index.html\">\\\n",
    "University of Minnesota</a>',\n",
    "    # showlegend = False,\n",
    "    autosize = False,\n",
    "    width = 1000,\n",
    "    height = 900,\n",
    "    hovermode = False,\n",
    "    legend = dict(\n",
    "        x=0.7,\n",
    "        y=-0.1,\n",
    "        bgcolor=\"rgba(255, 255, 255, 0)\",\n",
    "        font = dict( size=11 ),\n",
    "    )\n",
    ")\n",
    "years = df['YEAR'].unique()\n",
    "\n",
    "for i in range(len(years)):\n",
    "    geo_key = 'geo'+str(i+1) if i != 0 else 'geo'\n",
    "    lons = list(df[ df['YEAR'] == years[i] ]['LON'])\n",
    "    lats = list(df[ df['YEAR'] == years[i] ]['LAT'])\n",
    "    # Walmart store data\n",
    "    data.append(\n",
    "        dict(\n",
    "            type = 'scattergeo',\n",
    "            showlegend=False,\n",
    "            lon = lons,\n",
    "            lat = lats,\n",
    "            geo = geo_key,\n",
    "            name = years[i],\n",
    "            marker = dict(\n",
    "                color = \"rgb(0, 0, 255)\",\n",
    "                opacity = 0.5\n",
    "            )\n",
    "        )\n",
    "    )\n",
    "    # Year markers\n",
    "    data.append(\n",
    "        dict(\n",
    "            type = 'scattergeo',\n",
    "            showlegend = False,\n",
    "            lon = [-78],\n",
    "            lat = [47],\n",
    "            geo = geo_key,\n",
    "            text = [years[i]],\n",
    "            mode = 'text',\n",
    "        )\n",
    "    )\n",
    "    layout[geo_key] = dict(\n",
    "        scope = 'usa',\n",
    "        showland = True,\n",
    "        landcolor = 'rgb(229, 229, 229)',\n",
    "        showcountries = False,\n",
    "        domain = dict( x = [], y = [] ),\n",
    "        subunitcolor = \"rgb(255, 255, 255)\",\n",
    "    )\n",
    "\n",
    "\n",
    "def draw_sparkline( domain, lataxis, lonaxis ):\n",
    "    ''' Returns a sparkline layout object for geo coordinates  '''\n",
    "    return dict(\n",
    "        showland = False,\n",
    "        showframe = False,\n",
    "        showcountries = False,\n",
    "        showcoastlines = False,\n",
    "        domain = domain,\n",
    "        lataxis = lataxis,\n",
    "        lonaxis = lonaxis,\n",
    "        bgcolor = 'rgba(255,200,200,0.0)'\n",
    "    )\n",
    "\n",
    "# Stores per year sparkline\n",
    "layout['geo44'] = draw_sparkline({'x':[0.6,0.8], 'y':[0,0.15]}, \\\n",
    "                                 {'range':[-5.0, 30.0]}, {'range':[0.0, 40.0]} )\n",
    "data.append(\n",
    "    dict(\n",
    "        type = 'scattergeo',\n",
    "        mode = 'lines',\n",
    "        lat = list(df.groupby(by=['YEAR']).count()['storenum']/1e1),\n",
    "        lon = range(len(df.groupby(by=['YEAR']).count()['storenum']/1e1)),\n",
    "        line = dict( color = \"rgb(0, 0, 255)\" ),\n",
    "        name = \"New stores per year<br>Peak of 178 stores per year in 1990\",\n",
    "        geo = 'geo44',\n",
    "    )\n",
    ")\n",
    "\n",
    "# Cumulative sum sparkline\n",
    "layout['geo45'] = draw_sparkline({'x':[0.8,1], 'y':[0,0.15]}, \\\n",
    "                                 {'range':[-5.0, 50.0]}, {'range':[0.0, 50.0]} )\n",
    "data.append(\n",
    "    dict(\n",
    "        type = 'scattergeo',\n",
    "        mode = 'lines',\n",
    "        lat = list(df.groupby(by=['YEAR']).count().cumsum()['storenum']/1e2),\n",
    "        lon = range(len(df.groupby(by=['YEAR']).count()['storenum']/1e1)),\n",
    "        line = dict( color = \"rgb(214, 39, 40)\" ),\n",
    "        name =\"Cumulative sum<br>3176 stores total in 2006\",\n",
    "        geo = 'geo45',\n",
    "    )\n",
    ")\n",
    "\n",
    "z = 0\n",
    "COLS = 5\n",
    "ROWS = 9\n",
    "for y in reversed(range(ROWS)):\n",
    "    for x in range(COLS):\n",
    "        geo_key = 'geo'+str(z+1) if z != 0 else 'geo'\n",
    "        layout[geo_key]['domain']['x'] = [float(x)/float(COLS), float(x+1)/float(COLS)]\n",
    "        layout[geo_key]['domain']['y'] = [float(y)/float(ROWS), float(y+1)/float(ROWS)]\n",
    "        z=z+1\n",
    "        if z > 42:\n",
    "            break\n",
    "\n",
    "fig = { 'data':data, 'layout':layout }\n",
    "#py.iplot( fig, filename='US Walmart growth', height=900, width=1000 )\n",
    "url = py.plot( fig, validate=False, filename='US Walmart growth.html' )\n",
    "py.iplot( fig, filename='US Walmart growth' )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
